using System.Collections.Generic;
using Lucene.Net.Search;

namespace NopSolutions.NopCommerce.LuceneHelper.Queries
{
    public abstract class BaseSpecificationQuery<T> : BaseQuery<T> where T : BaseQuery<T>
    {
        public const string FIELDS_CATEGORY_ID = "CategoryID";
        public const string FIELDS_MANUFACTURER_ID = "ManufacturerID";
        public const string FIELDS_SPECIFICATION_ATTRIBUTE_ID = "SpecID";
        public const string FIELDS_SPECIFICATION_ATTRIBUTE_NAME = "SpecName";
        public const string FIELDS_SPECIFICATION_ATTRIBUTE_DISPLAYORDER = "SpecDisplayOrder";

        public T WithCategories(IList<int> categories)
        {
            if (categories.Count > 0)
            {
                Query = JoinQueries(Query, GetQueryFromList(categories, FIELDS_CATEGORY_ID));
            }
            return this as T;
        }

        public T WithCategory(int category)
        {
            WithCategories(new List<int> { category });
            return this as T;
        }

        public T WithManufacturers(IList<int> manufacturers)
        {
            if (manufacturers.Count > 0)
            {
                Query = JoinQueries(Query, GetQueryFromList(manufacturers, FIELDS_CATEGORY_ID));
            }
            return this as T;
        }

        public T ExcludeSpecificationAttributes(IEnumerable<int> specificationAttributeIds)
        {
            var booleanQuery = new BooleanQuery();
            if (Query != null)
            {
                booleanQuery.Add(Query, BooleanClause.Occur.MUST);
            }
            foreach (var specificationAttributeId in specificationAttributeIds)
            {
                booleanQuery.Add(TermQuery(FIELDS_SPECIFICATION_ATTRIBUTE_ID, specificationAttributeId.ToString()),
                                 BooleanClause.Occur.MUST_NOT);
            }
            Query = booleanQuery;
            return this as T;
        }

        public T WithManufacturer(int manufacturer)
        {
            WithManufacturers(new List<int> { manufacturer });
            return this as T;
        }

        public T WithContext(FilterContext context)
        {
            var instance = this;
            if (context.Categories.Count > 0)
            {
                WithCategories(context.Categories);
            }
            if (context.Manufacturers.Count > 0)
            {
                WithManufacturers(context.Manufacturers);
            }
            return this as T;
        }
    }
}
